package online.chazi.bootplus.multiple.datasource;

import lombok.extern.slf4j.Slf4j;
import online.chazi.bootplus.multiple.datasource.router.MultipleDataSourceBalanceRouter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import java.util.*;

/**
 * 说明：作者很懒，什么都没留下
 * Created by 叉子同学 on 2020-05-13 10:22
 */
@Slf4j
public class MultipleDataSource extends AbstractRoutingDataSource {

    public static final String GROUP_SEPARATOR = "-";
    private static final ThreadLocal<Deque<String>> LOCAL_CONTEXT = ThreadLocal.withInitial(ArrayDeque::new);
    //负载均衡
    private static final Map<String, List<String>> GROUP_DATA_SOURCE = new HashMap<>();
    //默认primary
    private String primary;
    private MultipleDataSourceBalanceRouter multipleDataSourceBalanceRouter;

    public MultipleDataSource(String primary, MultipleDataSourceBalanceRouter multipleDataSourceBalanceRouter) {
        this.primary = primary;
        this.multipleDataSourceBalanceRouter = multipleDataSourceBalanceRouter;
    }

    //这只的时候 name: slave-1
    //其中，groupName=slave  name=slave-1
    public void addGroupDataSource(String name, Integer weight) {
        String groupName = getGroupName(name);
        log.info("载入分组:{}", groupName);
        List<String> list = GROUP_DATA_SOURCE.computeIfAbsent(groupName, k -> new ArrayList<>());
        list.add(name);
        multipleDataSourceBalanceRouter.initWeight(name, weight);
    }

    public static void push(String name) {
        LOCAL_CONTEXT.get().push(StringUtils.isEmpty(name) ? "" : name);
    }

    public static void poll() {
        Deque<String> deque = LOCAL_CONTEXT.get();
        deque.poll();
        if (deque.isEmpty()) {
            LOCAL_CONTEXT.remove();
        }
    }

    public static void clear() {
        LOCAL_CONTEXT.remove();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String ds = LOCAL_CONTEXT.get().peek();
        if (ds == null) ds = this.primary;
        log.info("使用:{}", ds);

        //@UsingDataSource(name = "slave-1")  这种注解不使用负载均衡
        //@UsingDataSource(name = "slave")    可以使用负载均衡

        //是否存在分组
        if (GROUP_DATA_SOURCE.containsKey(ds)) {
            ds = multipleDataSourceBalanceRouter.determineLookupKey(ds, GROUP_DATA_SOURCE.get(ds));
        }

        return ds;
    }

    public static String getGroupName(String name) {
        return name.split(GROUP_SEPARATOR)[0];
    }

}
